/*******************************************************************************
 * 版权：北京润尼尔网络科技有限公司，保留所有版权<br>
 * 版本：v1.0.0<br>
 * 文件：Draw2dGraphicalEditor.js<br>
 * 日期：2016年10月11日<br>
 * 作者: 王志远<br>
 * 功能：2d图形编辑器<br>
 *
 * 修改记录：<br>
 * 日期 描述 更新功能<br>
 ******************************************************************************/

window.makeNamespace(window, "Rainier.UI.V2");

/**
 * 类型名称：Rainier.UI.V2.Draw2dGraphicalEditor<br>
 * 类型功能：编辑器基类<br>
 */
Rainier.UI.V2.Draw2dGraphicalEditor = Rainier.UI.V2.GraphicalEditor.extend({
  NAME: "Rainier.UI.V2.Draw2dGraphicalEditor",

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.init<br>
   * 函数功能：构造函数<br>
   * 参数输入：objPro:ViewProperty
   * 异常信息：无<br>
   */
  init: function (objPro) {
    this._super(objPro);
    this.rootEditPart = new Rainier.UI.V2.RootEditPart();
    this.rootModel = new Rainier.UI.V2.RootModel();
    this.context = new Rainier.UI.V2.Draw2dContext();
    this.runStatus = false; //判断当前实验是否处于解算状态
    this.storageExper = null;

    this.virtualModelList = {}; //存储虚拟仪器列表，方便动态调用
    this.canvas = null;
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.storeExper<br>
   * 函数功能：存储默认实验(主针对集成环境)<br>
   * 参数输入：exper ： Object<br>
   * 参数输出：无<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  storeExper: function (exper) {
    this.storageExper = exper;
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.onPropertyChange<br>
   * 函数功能：侦听模型事件信息<br>
   * 参数输入：evt:PropertyChangeEvent<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  onPropertyChange: function (evt) {
    var eventName = evt.getEventName();
    var oldValue = evt.getOldValue();
    var newValue = evt.getNewValue();
    this.editorObjectEventSupport.firePropertyChangeEvent(eventName, oldValue, newValue);
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.createComposite<br>
   * 函数功能：创建组件<br>
   * 参数输入：parent:父组件<br>
   * 参数输入：uiProperty界面属性<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  createComposite: function (parent, uiProperty, size) {
    var _this = this;
    //var canvasDom = $("<canvas id='canvasDom'></canvas>");
    //parent.append(canvasDom);
    var canvasComposite = new Rainier.UI.V2.UICompositeDraw2dCanvas(parent, {
      width: canvasWidth,
      height: canvasHeight,
    });

    //变量初始化
    var canvas = canvasComposite.canvas; //绘图帆布
    this.canvas = canvas;
    var rootEditPart = this.rootEditPart; //根编辑器
    var rootModel = this.rootModel; //根模型
    var context = this.context; //编辑器上下文环境
    if (size) {
      canvas.setZoom(canvas.getZoom() * 1.4, true);
    } else {
      console.log(canvas.getZoom());
      canvas.setZoom(canvas.getZoom() * 1.0, true);
    }
    // canvas.enableWheel();

    // 控制首页滚动条位置
    var canvasHtmlContainer = canvas.getHtmlContainer();
    var canvasParent = canvasHtmlContainer.parent().parent();
    console.log(canvasHtmlContainer[0].scrollWidth);
    console.log(canvasHtmlContainer[0].scrollHeight);
    // window.scrollTo(canvasHtmlContainer[0].scrollWidth / 2, canvasHtmlContainer[0].scrollHeight / 2);

    //设置图元EditPolicy
    this.rootEditPart.setFigure(canvas);
    this.rootEditPart.setModel(rootModel);

    //初始化上下文环境
    this.context.setRootEditPart(rootEditPart);
    this.context.setRootModel(rootModel);
    this.context.setRootFigure(canvas);
    this.context.setCircuitParser();

    //初始化命令堆栈
    this.commandStack = canvas.getCommandStack();

    //侦听模型事件
    this.rootEditPart.addModelEventListener("modelEventListener", this);
    this.rootEditPart.addModelEventListener("modelEventListenerForContext", this.context);

    //初始化组件（组件赋值）
    this.composite = canvasComposite;

    // var Listener = Rainier.UI.V2.UIEventListener.extend({

    // 	NAME : 'listener',

    // 	init : function(){
    // 		this._super();
    // 	},

    // 	onEvent : function(sEvent,eventSource,args){
    // 		var width  = args[0];
    // 		var height = args[1];
    // 		var zoom = canvas.getZoom();
    // 		if(width < _this.initWidth){
    // 			canvas.setZoom(zoom + 0.3,true);
    // 			_this.initWidth = width;
    // 		}else if(width > _this.initWidth){
    // 			canvas.setZoom(zoom - 0.3,true);
    // 			_this.initWidth = width;
    // 		}
    // 	},
    // });

    // parent.registerEventListener("onResize",new Listener());

    if (this.storageExper) {
      this.doRestore(this.storageExper);
    }
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.installEditPartFactory<br>
   * 函数功能：安装元件创建工厂<br>
   * 参数输入：factory:Rainier.UI.V2.EditPartFactory<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  installEditPartFactory: function (factory) {
    this.rootEditPart.installEditPartFactory(factory);
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.enterCreateState<br>
   * 函数功能：进入器件创建状态<br>
   * 参数输入：sModelClassName:String<br>
   * 参数输出：modelProperty:{
   * 		uiProperty:{
   * 		},
   * 		modelProperty:{
   * 		}
   * }<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  enterCreateState: function (sModelClassName, modelProperty, sJson) {
    this.rootEditPart.enterCreateState(sModelClassName, modelProperty, sJson);
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.enterRunStatus<br>
   * 函数功能：进入解算状态<br>
   * 参数输入：无<br>
   * 参数输出：无<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  enterRunStatus: function () {
    this.getVirtualModel();
    var dsvList = this.getDSVirtualModel();
    $.each(dsvList, function (index, dsv) {
      dsv.startCvi(true);
    });
    $.each(this.virtualModelList, function (i, model) {
      model.sendStartToCvi("restart");
    });
    this.runStatus = true;
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.leaveRunStatus<br>
   * 函数功能：退出解算状态<br>
   * 参数输入：无<br>
   * 参数输出：无<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  leaveRunStatus: function () {
    var dsvList = this.getDSVirtualModel();
    $.each(dsvList, function (index, dsv) {
      dsv.closeCvi();
    });
    $.each(this.virtualModelList, function (i, model) {
      model.sendStartToCvi("stop");
    });
    this.runStatus = false;
    this.virtualModelList = {};
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.getRunStatus<br>
   * 函数功能：获取解算状态<br>
   * 参数输入：无<br>
   * 参数输出：无<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  getRunStatus: function () {
    return this.runStatus;
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.getDSVirtualModel<br>
   * 函数功能：获取所有启动虚拟仪器<br>
   * 参数输入：无<br>
   * 参数输出：无<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  getVirtualModel: function () {
    var _this = this;
    var children = this.rootModel.getChildren();
    this.virtualModelList = {};
    $.each(children, function (index, child) {
      if (child instanceof Rainier.UI.V2.VirtualModel) {
        var label = child.getProperty().modelProperty.label;
        if (label) {
          _this.virtualModelList[label.toLowerCase()] = child;
        }
      }
    });
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.getDSVirtualModel<br>
   * 函数功能：获取默认启动虚拟仪器<br>
   * 参数输入：无<br>
   * 参数输出：无<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  getDSVirtualModel: function () {
    var _this = this;
    var unitList = [];
    var children = this.rootModel.getChildren();
    $.each(children, function (index, child) {
      if (child instanceof Rainier.UI.V2.DSVirtualModel) {
        unitList.push(child);
      }
    });
    return unitList;
  },

  /**
   * 函数名称：Rainier.UI.V2.GraphicalEditor.doSave<br>
   * 函数功能：执行保持<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  doSave: function (expName) {
    var json = {};

    var description = {};
    var version = null;
    var modelJson = null;
    var user = null;

    if (this.rootModel) {
      modelJson = this.rootModel.serializeToJson();
    }

    //填充基本信息
    json.experimentInfo = {};
    json.experimentInfo.experimentName = expName;
    json.experimentInfo.configuretion = this.context.experimentCfg || "";
    json.experimentInfo.zoom = this.context.getRootFigure().getZoom();

    //填充实验脚本
    json.experimentScene = modelJson;

    //填充实验步骤信息
    json.stepByStep = [];

    return json;
  },

  /**
   * 函数名称：Rainier.UI.V2.GraphicalEditor.doSaveAs<br>
   * 函数功能：执行另存为<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  doSaveAs: function (expName) {
    var json = this.doSave(expName);
    return json;
  },

  /**
   * 函数名称：Rainier.UI.V2.GraphicalEditor.doRestore<br>
   * 函数功能：执行恢复过程<br>
   * 参数输入：objJson Json格式对象输入<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  doRestore: function (objJson) {
    this.clearEditor();

    var _this = this;
    var components = null;
    var connections = null;
    if (objJson.experimentInfo.configuretion) {
      _this.context.experimentCfg = objJson.experimentInfo.configuretion;
    }
    if (objJson.experimentInfo.zoom) {
      _this.context.getRootFigure().setZoom(objJson.experimentInfo.zoom, true);
    }

    if (objJson.experimentScene) {
      components = objJson.experimentScene.componentList ? objJson.experimentScene.componentList : null;
    }

    if (objJson.experimentScene) {
      connections = objJson.experimentScene.connectionList ? objJson.experimentScene.connectionList : null;
    }

    //恢复所有器件
    if (components) {
      //分块处理 创建元器件  模拟requestIdleCallback
      _this.performChunkHandle(
        components,
        (com) => {
          // console.log("画元器件", com);
          var pro = com.uiProperty;
          var model = Rainier.UI.V2.DeviceModelBuilder.buildModel(com);
          if (model) {
            _this.rootModel.addChildModel(model);
            model.setPosition(pro.x, pro.y, false);
          }
        },
        (task) => {
          //如何分割执行块
          setTimeout(() => {
            task((time) => time < 16);
          }, 0);
        }
      );
      // if (window.requestIdleCallback) {
      //   _this.performChunk(components, (com) => {
      //     var pro = com.uiProperty;
      //     var model = Rainier.UI.V2.DeviceModelBuilder.buildModel(com);
      //     if (model) {
      //       _this.rootModel.addChildModel(model);
      //       model.setPosition(pro.x, pro.y, false);
      //     }
      //   });
      // } else {
      //   _this.performChunkHandle(
      //     components,
      //     (com) => {
      //       var pro = com.uiProperty;
      //       var model = Rainier.UI.V2.DeviceModelBuilder.buildModel(com);
      //       if (model) {
      //         _this.rootModel.addChildModel(model);
      //         model.setPosition(pro.x, pro.y, false);
      //       }
      //     },
      //     (task) => {
      //       //如何分割执行块
      //       setTimeout(() => {
      //         task((time) => time < 16);
      //       }, 0);
      //     }
      //   );
      // $.each(components, function (i, com) {
      //   var pro = com.uiProperty;
      //   var model = Rainier.UI.V2.DeviceModelBuilder.buildModel(com);
      //   if (model) {
      //     _this.rootModel.addChildModel(model);
      //     model.setPosition(pro.x, pro.y, false);
      //   }
      // });
      // }
    }

    //恢复连接
    var unrestoredConnections = new draw2d.util.ArrayList();
    if (connections) {
      $.each(connections, function (i, conn) {
        unrestoredConnections.add(conn);
      });
    }

    // if (window.requestIdleCallback) {
    //   run();
    // } else {
    //   for (var i = 0; unrestoredConnections.getSize() > 0; ) {
    //     var connDes = unrestoredConnections.get(i);
    //     var sid = connDes.modelProperty.source_id;
    //     var tid = connDes.modelProperty.target_id;
    //     var spid = connDes.modelProperty.source_parent_id;
    //     var tpid = connDes.modelProperty.target_parent_id;
    //     var sPort = this.context.findPortModelById(spid, sid);
    //     var tPort = this.context.findPortModelById(tpid, tid);
    //     var restored = false;
    //     if (sPort && tPort) {
    //       this.makeConnection(sPort, tPort, connDes);
    //       restored = true;
    //     }
    //     if (restored) {
    //       unrestoredConnections.remove(connDes);
    //       i = 0;
    //       continue;
    //     }
    //     i++;
    //   }
    // }
    // console.log("unrestoredConnections", unrestoredConnections);

    //执行一块任务

    function run() {
      var i = 0;
      if (unrestoredConnections.getSize() <= 0) return;
      setTimeout(() => {
        const now = Date.now();
        //直到线画完为止  unrestoredConnections.getSize() <= 0 就终止画线
        while (Date.now() - now < 16 && unrestoredConnections.getSize() > 0) {
          var connDes = unrestoredConnections.get(i);
          // console.log("画线", connDes);
          if (connDes) {
            var sid = connDes.modelProperty.source_id;
            var tid = connDes.modelProperty.target_id;
            var spid = connDes.modelProperty.source_parent_id;
            var tpid = connDes.modelProperty.target_parent_id;
            var sPort = _this.context.findPortModelById(spid, sid);
            var tPort = _this.context.findPortModelById(tpid, tid);
            var restored = false;
            if (sPort && tPort) {
              _this.makeConnection(sPort, tPort, connDes);
              restored = true;
            }
            if (restored) {
              console.log("restored", restored);
              unrestoredConnections.remove(connDes);
              i = 0;
              // continue;
            } else {
              // debugger;
              i++;
            }
          }

          // i++;
        }
        run();
      }, 30);
    }
    run();

    // if (window.requestIdleCallback) {
    //   run();
    // } else {
    //   for (var i = 0; unrestoredConnections.getSize() > 0; ) {
    //     var connDes = unrestoredConnections.get(i);
    //     var sid = connDes.modelProperty.source_id;
    //     var tid = connDes.modelProperty.target_id;
    //     var spid = connDes.modelProperty.source_parent_id;
    //     var tpid = connDes.modelProperty.target_parent_id;
    //     var sPort = this.context.findPortModelById(spid, sid);
    //     var tPort = this.context.findPortModelById(tpid, tid);
    //     var restored = false;
    //     if (sPort && tPort) {
    //       this.makeConnection(sPort, tPort, connDes);
    //       restored = true;
    //     }
    //     if (restored) {
    //       unrestoredConnections.remove(connDes);
    //       i = 0;
    //       continue;
    //     }
    //     i++;
    //   }
    // }
    // console.log("unrestoredConnections", unrestoredConnections);
    // function run() {
    //   var i = 0;
    //   requestIdleCallback((idle) => {
    //     while (idle.timeRemaining() > 0 && unrestoredConnections.getSize() > 0) {
    //       var connDes = unrestoredConnections.get(i);
    //       // console.log("connDes", connDes);
    //       if (connDes) {
    //         var sid = connDes.modelProperty.source_id;
    //         var tid = connDes.modelProperty.target_id;
    //         var spid = connDes.modelProperty.source_parent_id;
    //         var tpid = connDes.modelProperty.target_parent_id;
    //         var sPort = _this.context.findPortModelById(spid, sid);
    //         var tPort = _this.context.findPortModelById(tpid, tid);
    //         var restored = false;
    //         if (sPort && tPort) {
    //           _this.makeConnection(sPort, tPort, connDes);
    //           restored = true;
    //         }
    //         if (restored) {
    //           unrestoredConnections.remove(connDes);
    //           i = 0;
    //           // continue;
    //         } else {
    //           i++;
    //         }
    //       }

    //       // i++;
    //     }
    //     run();
    //   });
    // }

    // this.context.circuitparser.parse(true);
    this.commandStack.undostack = [];
    this.commandStack.redostack = [];

    var arr = [1];
    var len;
    // 已使用器材本地恢复
    for (var c = 0; c < (len = (components = components || arr).length); c++) {
      if (componentName != undefined) {
        var componentName = components[c].modelProperty.componentName;
        var className = components[c].modelProperty.typeName;
        this.restoreUsedPart(className, componentName);
        if (components == null) {
          console.log(1212);
        }
      }
    }
  },
  //兼容处理
  //1.如何分割执行块
  //2.还有执行时间吗
  performChunkHandle: function (datas, cb, chunkSplitor) {
    var that = this;
    // $.loading.open();
    if (datas.length == 0) return;
    let i = 0; //目前应该取出的任务下标
    //执行一块任务
    function run() {
      if (i > datas.length) return;
      chunkSplitor((hasTime) => {
        //timeRemaining: () => number // 当前剩余的可用时间。即该帧剩余时间。
        //didTimeout: boolean // 是否超时。
        const now = Date.now();
        // console.log("i", i);
        // console.log("datas.length", datas.length);
        while (hasTime(Date.now() - now) && i <= datas.length) {
          //在这一帧还有空闲时间
          if (i < datas.length) {
            cb(datas[i], i);
          }
          if (datas.length - 1 <= i) {
            $.loading.close();
            $.canvasScaleTranslate.scrollToByFirstFigure(that.canvas.getZoom());
            window.selectTreeNode && $.propComp.selectPartlib(window.selectTreeNode);
            window.selectTreeNode = null;
          }
          i++;
        }
        run();
      });
    }
    run();
  },
  performChunk(datas, cb) {
    var that = this;
    if (datas.length == 0) return;
    let i = 0;

    function run() {
      requestIdleCallback((idle) => {
        while (idle.timeRemaining() > 0 && i <= datas.length) {
          if (i < datas.length) {
            cb(datas[i], i);
          } else if (datas.length == i) {
            window.selectTreeNode && $.propComp.selectPartlib(window.selectTreeNode);
            window.selectTreeNode = null;
          }

          // let com = datas[i];
          // var pro = com.uiProperty;
          // var model = Rainier.UI.V2.DeviceModelBuilder.buildModel(com);
          // if (model) {
          //   that.rootModel.addChildModel(model);
          //   model.setPosition(pro.x, pro.y, false);
          // }
          i++;
        }
        run();
      });
    }
    run();
  },
  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.restoreUsedPart<br>
   * 函数功能：(单个添加器件)判断器材展示栏中是否已存在该器材，若存在则不再再次向展示栏中添加<br>
   * 函数输入：className和componentName
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  restoreUsedPart: function (className, componentName) {
    // if(className == "OverThreeTextModelJson" || className === "TextModelJson2" || className === "TextModelJson3"){
    // 	className = "TextModelJson";
    // }
    var usedPart = {};
    usedPart.isLogic = true;
    usedPart.courseType = "Communication";
    usedPart.deviceType = "PmsModel";
    //data_part:data的一个对象
    var data_part = {};
    data_part.className = className;
    // 还未向实验台添加器件时
    if (data.length == 0) {
      if (className) {
        data_part.addCount = 1;
      }
      data.push(data_part);
      usedPart.className = data[0].className;
      usedPart.componentName = componentName;
      usedPartArray.push(usedPart);
      // console.log(data);
      // console.log(usedPartArray);
      // 实验台上已经存在器件时
    } else {
      for (var i = 0; i < data.length; i++) {
        if (data[i].className == className) {
          // console.log("已加入已使用器件数组!");
          data[i].addCount += 1;
          // console.log(data);
          return;
        }
      }
      data_part.addCount = 1;
      data.push(data_part);
      usedPart.className = data[data.length - 1].className;
      usedPart.componentName = componentName;
      usedPartArray.push(usedPart);
      // console.log(data);
      // console.log(usedPartArray);
    }
    // console.log(usedPartArray);
    // console.log(data);
  },

  /**
   * 函数名称：Rainier.UI.V2.GraphicalEditor.makeConnection<br>
   * 函数功能：创建连接<br>
   * 参数输入：sourcePort:PortModel<br>
   * 参数输入：targetPort:PortModel<br>
   * 参数输入：conndes:Object（连接描述对象）<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  makeConnection: function (sourcePort, targetPort, conndes) {
    var property = {};
    property.uiProperty = $.extend(true, {}, conndes.uiProperty);
    property.modelProperty = $.extend(true, {}, conndes.modelProperty);

    var conn = new Rainier.UI.V2.ConnectionModel(property);
    conn.label = property.modelProperty.label;
    conn.setUuid(conndes.uuid);
    conn.attachSourcePort(sourcePort);
    sourcePort.attachOutgoing(conn);
    conn.attachTargetPort(targetPort);
    targetPort.attachIncoming(conn);
    this.rootModel.addConnection(conn);

    if (conndes.componentList) {
      $.each(conndes.componentList, function (i, joint) {
        var model = Rainier.UI.V2.DeviceModelBuilder.buildModel(joint);
        if (model) {
          conn.addChildModel(model, false);
        }
      });
    }
  },

  /**
   * @名称   clearEditor
   * @功能   清空实验平台的内容
   * @author 杨顺强
   * @data   2017-09-07
   * @return {[type]}   [description]
   */
  clearEditor: function () {
    var canvas = this.rootEditPart.figure;
    var figures = canvas.getFigures();
    var lines = canvas.getLines();
    canvas.getCommandStack().startTransaction(draw2d.Configuration.i18n.command.deleteShape);
    figures.each(function (index, figure) {
      var cmd = figure.createCommand(new draw2d.command.CommandType(draw2d.command.CommandType.DELETE));
      if (cmd !== null) {
        canvas.getCommandStack().execute(cmd);
      }
    });
    // execute all single commands at once.
    canvas.getCommandStack().commitTransaction();
  },
});
//画布高宽
canvasWidth = 20000;
canvasHeight = 20000;
